home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / HippoDraw / HippoDrawSrc1.1 / Hippo.subproj / InspectTuple.m < prev    next >
Encoding:
Text File  |  1992-04-25  |  17.0 KB  |  695 lines

  1. /* InspectTuple    by Paul Kunz    October 1991
  2.  * The supervisor for the tuple inspection panel
  3.  * 
  4.  * Copyright (C)  1991  The Board of Trustees of
  5.  * The Leland Stanford Junior University.  All Rights Reserved.
  6.  */ 
  7.  
  8. #import "InspectTuple.h"
  9.  
  10. const char InspectTuple_h_rcsid[] = INSPECTTUPLE_H_ID;
  11. const char InspectTuple_m_rcsid[] = "$Id: InspectTuple.m,v 1.27 1992/04/19 21:42:20 pfkeb Rel $";
  12.  
  13. #import <appkit/Application.h>
  14. #import <appkit/Box.h>
  15. #import <appkit/Form.h>
  16. #import <appkit/Matrix.h>
  17. #import <appkit/NXBrowser.h>
  18. #import <appkit/NXBrowserCell.h>
  19. #import <appkit/OpenPanel.h>
  20. #import <appkit/Pasteboard.h>
  21. #import <appkit/TextField.h>
  22. #import <appkit/Window.h>
  23. #import <appkit/nextstd.h>
  24. #import <objc/List.h>
  25. #import "DrawDocument.h"
  26. #import "HDraw.h"
  27. #import "HGraphicView.h"
  28. #import "HTuple.h"
  29. #import "NewInspector.h"
  30. #import "Plot.h"
  31. #import "stdio.h"
  32. #import "strings.h"
  33. #import <appkit/defaults.h>
  34. #import <sys/types.h>
  35. #import <sys/stat.h>
  36.  
  37. @implementation InspectTuple
  38. - initInspFor:aDraw
  39. {
  40.     [super initInspFor:aDraw];
  41.     
  42.     [NXApp loadNibSection:"InspectTuple.nib" owner:self
  43.            withNames:NO fromZone:[self zone]];
  44.     [theInspector addView:[contentBox contentView]
  45.                   withName:"Tuple List"
  46.           withSupervisor:self];
  47.     
  48.     openPanel = [OpenPanel new];
  49.   /* the following avoids getting "/private/Net/..." as default */
  50.     [openPanel setDirectory:NXHomeDirectory()];
  51.  
  52.     tupleList = [[ List allocFromZone:[self zone]] init]; 
  53.     
  54.     [[fileForm cellAt: 0 :0 ] setSelectable:YES];
  55.     [[fileForm cellAt: 1 :0 ] setEditable:NO];
  56.     [[fileForm cellAt: 2 :0 ] setEditable:NO];
  57.     [[fileForm cellAt: 3 :0 ] setEditable:NO];
  58.     [ fileForm setBordered:YES];
  59.     
  60.     return self;
  61. }
  62. - hTupleForTuple:(ntuple) nt
  63. {
  64.     id            hTuple;
  65.     int            i, count;
  66.     
  67.     count = [tupleList count];
  68.     for ( i = 0; i < count; i++ ) {
  69.         hTuple = [tupleList objectAt:i];
  70.     if ( nt == [hTuple ntuple] ) {
  71.         return hTuple;
  72.     }
  73.     }
  74.     return nil;
  75. }
  76.  
  77. - (BOOL) isNewTupleFile:(const char *)filename
  78. {
  79.     id            hTuple;
  80.     int            i, count;
  81.     
  82.     count = [tupleList count];
  83.     for ( i = 0; i < count; i++ ) {
  84.         hTuple = [tupleList objectAt:i];
  85.     if ( strcmp( [hTuple filename], filename ) == 0 ) {
  86.         return NO;
  87.     }
  88.     }
  89.     return YES;
  90. }
  91. - hTupleForFile:(const char *)filename index:(int)iValue
  92. {
  93.     const char    *altfile;
  94.     id        hTuple;
  95.     int        i;
  96.     
  97.     i = [tupleList count];
  98.     while ( i-- ) {
  99.         hTuple = [tupleList objectAt:i];
  100.     if ( [hTuple index] == iValue ) {
  101.         if ( strcmp( [hTuple filename], filename ) == 0 ) {
  102.         return hTuple;
  103.         }
  104.         altfile = [hTuple altfilename];
  105.         if ( altfile && (strcmp(altfile, filename) == 0 ) ) {
  106.         return hTuple;
  107.         }
  108.     }
  109.     }
  110.     
  111.     return nil;
  112. }
  113. - (int) runModelForTypes
  114. {
  115.     static const char    *const filetype[2] = {"hippo", NULL};
  116.     
  117.     [openPanel setAccessoryView:accessoryView];
  118.     if ( ![openPanel runModalForTypes:filetype] ) {
  119.         return HD_CANCEL;
  120.     }
  121.     return HD_OK;
  122. }
  123. - openTuple:sender
  124. {
  125.     int            irc;
  126.  
  127.     irc = [self runModelForTypes];
  128.     if ( irc == HD_CANCEL ) {
  129.         return self;
  130.     }
  131.     [self openTupleFile];
  132.     return self;
  133. }
  134. - openTupleAsText:sender
  135. {
  136.     [openPanel setAccessoryView:accessoryView];
  137.     if ( ![openPanel runModal] ) {
  138.         return self;
  139.     }
  140.     [self openTupleFile];
  141.     return self;
  142. }
  143. - openTupleFile
  144.     const char        *filename;
  145.     int                 irc;
  146.     BOOL        refFlag;
  147.  
  148.     filename = [openPanel filename];
  149.     refFlag = [refFlagMatrix selectedRow] ? NO : YES;
  150.     irc = [self openTupleFile:filename by:refFlag];
  151.     if ( irc == HD_REPLACE ) {
  152.         [self bindDisplays];
  153.     }
  154.     [self showPanel];
  155.     return self;
  156. }
  157.  
  158. - openTupleFromFile:(const char *)filename by:(BOOL)refFlag
  159. {
  160.     id        hTuple, newTupleList;
  161.     FILE    *infile;
  162.     ntuple    *ntlist;
  163.     display     *dlist;
  164.     char    *suffix;
  165.     int        i, irc;
  166.     BOOL    binFlag;
  167.     
  168.     suffix = rindex(filename, '.' );
  169.     if ( (infile = fopen(filename, "r") ) == NULL ) {
  170.     irc = NXRunAlertPanel("Reason Alert", "Couldn't open file",
  171.             "OK", NULL, NULL);
  172.     return nil;
  173.     }
  174.     if ( suffix && (strcmp(suffix, ".hippo" ) == 0) ) {
  175.         binFlag = YES;
  176.     if ( h_readStream(infile, &dlist, &ntlist) != 0 ) {
  177.         return nil;
  178.     }
  179.     } else {
  180.         binFlag = NO;
  181.         NX_ZONEMALLOC( [self zone], ntlist, ntuple, 2 );
  182.     if ( !(ntlist[0] = h_fileParse( infile, NULL, 0) ) ) {
  183.         NXZoneFree([self zone], ntlist);
  184.         return nil;
  185.     }
  186.     ntlist[1] = NULL;
  187.     }
  188.     irc = fclose( infile );
  189.     
  190.     newTupleList = [[List allocFromZone:[self zone]] initCount:0];
  191.     for ( i = 0; ntlist[i] != NULL; i++ ) {
  192.     hTuple = [[HTuple allocFromZone:[self zone]]
  193.                       initTuple:ntlist[i] file:filename
  194.               by:refFlag mode:binFlag index:i];
  195.     [tupleList addObject:hTuple];
  196.     [newTupleList addObject:hTuple];
  197.     }
  198.     [tupleBrowser loadColumnZero];
  199.     [ self setTuple:ntlist[0] ];
  200.     return newTupleList;
  201. }
  202. - openTuple:pasteBoard
  203.     userData:(const char *)args
  204.     error:(char **)errorMsg
  205. {
  206.     id        hTuple;
  207.     FILE     *infile;
  208.     ntuple    *ntlist;
  209.     const char *const *ptypes;
  210.     const char *data;
  211.     char     filename[25];
  212.     char    *outbuffer;
  213.     int        i, irc, length;
  214.     BOOL    binFlag;
  215.  
  216.     ptypes = [pasteBoard types];
  217.     for ( i = 0; ptypes[i]; i++ ) {
  218.         if ( !strcmp(ptypes[i], NXAsciiPboardType) ) {
  219.         [pasteBoard readType:ptypes[i] data:&data length:&length];
  220.         NX_ZONEMALLOC([self zone], outbuffer, char, (length+2) );
  221.         strncpy( outbuffer, data, length);
  222.         outbuffer[length] = '\n';
  223.         outbuffer[length+1] = '\0';
  224.         strcpy(filename,"/tmp/file000000Selection" );
  225.         NXGetTempFilename(filename,9);
  226.         infile=fopen(filename,"w");
  227.         fprintf(infile,outbuffer);
  228.         fclose(infile);
  229.         NXZoneFree([self zone], outbuffer);
  230.         if ( (infile = fopen(filename, "r") ) == NULL ) {
  231.         *errorMsg = "Couldn't open /tmp file";
  232.         return nil;
  233.         }
  234.         binFlag = NO;
  235.         NX_ZONEMALLOC( [self zone], ntlist, ntuple, 2 );
  236.         if ( !(ntlist[0] = h_fileParse( infile, NULL, 0) ) ) {
  237.         NXZoneFree([self zone], ntlist);
  238.         *errorMsg = "Couldn't interpret data as n-tuple";
  239.         return nil;
  240.         }
  241.         ntlist[1] = NULL;
  242.         irc = fclose( infile );
  243.         unlink(filename);
  244.         hTuple = [[HTuple allocFromZone:[self zone]]
  245.                           initTuple:ntlist[0] file:"From Pasteboard"
  246.                   by:NO mode:NO index:0];
  247.         [hTuple setFakeFilename:YES];
  248.         [tupleList addObject:hTuple];
  249.         [tupleBrowser loadColumnZero];
  250.         [self setTuple:ntlist[0] ];
  251.         [self showPanel];
  252.     }
  253.     }
  254.     return self;
  255. }
  256. - addTuple:(ntuple) nt
  257. {
  258.     id            hTuple;
  259.     
  260.     hTuple = [[HTuple allocFromZone:[self zone]]
  261.                    initTuple:nt file:"none"
  262.                       by:NO mode:YES index:0];
  263.     [hTuple setFakeFilename:YES];
  264.     [tupleList addObject:hTuple];
  265.     [tupleBrowser loadColumnZero];
  266.     [ self setTuple:nt];
  267.     return hTuple;
  268. }
  269. - (ntuple) currentTuple
  270. {
  271.     id            browserMatrix;
  272.     id            hTuple;
  273.     ntuple        nt;
  274.     int            index;
  275.     
  276.     browserMatrix = [tupleBrowser matrixInColumn:0];
  277.     index = [browserMatrix selectedRow];
  278.     if ( index >= 0 ) {
  279.         hTuple = [tupleList objectAt:index];
  280.         nt = [hTuple ntuple];
  281.     } else {
  282.         nt = NULL;
  283.     }
  284.     return nt;
  285. }
  286.  
  287. - currentHTuple
  288. {
  289.     id        browserMatrix;
  290.     id        hTuple;
  291.     int        index;
  292.     
  293.     browserMatrix = [tupleBrowser matrixInColumn:0];
  294.     index = [browserMatrix selectedRow];
  295.     if ( index >= 0 ) {
  296.         hTuple = [tupleList objectAt:index];
  297.     } else {
  298.         hTuple = nil;
  299.     }
  300.     return hTuple;
  301. }
  302.  
  303. - bindDisplays
  304. {
  305.     id        windowList;
  306.     id        window, document, view;
  307.     int        wcount;
  308.     
  309.     windowList = [NXApp windowList];
  310.     wcount = [windowList count];
  311.     while ( wcount-- ) {
  312.         window = [windowList objectAt:wcount];
  313.     document = [window delegate];
  314.     if ( [document isKindOf:[DrawDocument class]] ) {
  315.         view = [document view];
  316.         [view bindDisplays];
  317.             [view reDrawPlot];
  318.     }
  319.     }        
  320.     return self;
  321. }
  322.  
  323. - addTuplesIfAbsent:newList for:aView
  324. {
  325.     id        newTuple, hTuple;
  326.     int        newCount, count;
  327.     int        i, j, irc;
  328.     BOOL    isNew;
  329.     
  330.     newCount = [newList count];
  331.     for ( i = 0; i < newCount; i++ ) {
  332.         newTuple = [newList objectAt:i];
  333.     isNew = YES;
  334.     count = [tupleList count];
  335.     for ( j = 0; j < count; j++ ) {
  336.         hTuple = [tupleList objectAt:j];
  337.         if ( [hTuple isSameAs:newTuple] ) {
  338.             isNew = NO;
  339.         [aView replace:newTuple with:hTuple];
  340.         [newTuple free];
  341.         break;
  342.         }
  343.     }
  344.     if ( isNew ) {
  345.         if ( [newTuple isRef ] ) {
  346.             irc = [self openTupleFile:[newTuple filename] by:YES];
  347.         if ( irc == HD_NOTEXIST ) {
  348.             [ self openAltTupleFile:[newTuple filename]];
  349.         }
  350.         j = [tupleList count];
  351.         while ( j-- ) {
  352.             hTuple = [tupleList objectAt:j];
  353.             if ( [hTuple isSameAs:newTuple] ) {
  354.                 [aView replace:newTuple with:hTuple];
  355.             [newTuple free];
  356.             break;
  357.             }
  358.         }
  359.         } else {
  360.         [tupleList addObject:newTuple];
  361.         [tupleBrowser loadColumnZero];
  362.         [ self setTuple:[newTuple ntuple]];
  363.         }
  364.     }
  365.     }
  366.     [self showPanel];
  367.     return self;
  368. }
  369. - (int) openTupleFile:(const char *)filename by:(BOOL) refFlag
  370. {
  371.     id            newTupleList;
  372.     struct stat        statbuf;
  373.     int            irc, rvalue;
  374.     
  375.     
  376.     if ( stat(filename, &statbuf) ) {
  377.         return HD_NOTEXIST;
  378.     }
  379.     rvalue = HD_OK;
  380.     if( ![self isNewTupleFile:filename] ) {
  381.         irc = NXRunAlertPanel( "Open", "Tuple file already open",
  382.                            "Replace", "Cancel", NULL);
  383.     if ( irc != NX_ALERTDEFAULT ) {
  384.         return HD_CANCEL;
  385.     }
  386.     [self closeTupleFile:filename];
  387.     rvalue = HD_REPLACE;
  388.     }               
  389.     if ( !(newTupleList = [self openTupleFromFile:filename by:refFlag]) ) {
  390.     irc = NXRunAlertPanel("Open", "Couldn't open file",
  391.             "OK", NULL, NULL);
  392.     return HD_CANCEL;
  393.     }
  394.     [newTupleList free];
  395.     return rvalue;
  396. }
  397. - openAltTupleFile:(const char *)filename
  398. {
  399.     id            newTupleList;
  400.     id            hTuple;
  401.     const char         *newfilename;
  402.     char        *suffix;
  403.     float        gray;
  404.     int            i, count;
  405.     int            rows, cols;
  406.     int                 irc;
  407.     BOOL        refFlag;
  408.  
  409.     [msgMatrix getNumRows:&rows numCols:&cols];
  410.     for (i = 0; i < rows; i++) {
  411.     [[msgMatrix cellAt:i :0] setTextGray:0.];
  412.     }
  413.     [[msgMatrix cellAt:1 :0] setStringValue:filename];
  414.     
  415.     suffix = rindex(filename, '.');
  416.     if (suffix && (strcmp(suffix, ".hippo") == 0)) {
  417.     irc = [self runModelForTypes];
  418.     } else {
  419.     [openPanel setAccessoryView:accessoryView];
  420.     if ( ![openPanel runModal] ) {
  421.         irc = HD_CANCEL;
  422.     } else {
  423.         irc = HD_OK;
  424.         }
  425.     }
  426.     gray = [msgMatrix backgroundGray];
  427.     for (i = 0; i < rows; i++) {
  428.     [[msgMatrix cellAt:i :0] setTextGray:gray];
  429.     }
  430.     if ( irc == HD_CANCEL ) {
  431.         return self;
  432.     }
  433.     
  434.     newfilename = [openPanel filename];
  435.     if ( ![self isNewTupleFile:newfilename] ) {
  436.         newTupleList = [self tupleListForFile:newfilename];
  437.     count = [newTupleList count];
  438.     for ( i = 0; i < count; i++ ) {
  439.         hTuple = [newTupleList objectAt:i];
  440.         [hTuple setAltFilename:filename];
  441.     }
  442.     return self;
  443.     }
  444.     refFlag = [refFlagMatrix selectedRow] ? NO : YES;
  445.     if ( !(newTupleList = [self openTupleFromFile:newfilename by:refFlag]) ) {
  446.     irc = NXRunAlertPanel("Open", "Couldn't open file",
  447.             "OK", NULL, NULL);
  448.     return self;
  449.     }
  450.     count = [newTupleList count];
  451.     for ( i = 0; i < count; i++ ) {
  452.         hTuple = [newTupleList objectAt:i];
  453.     [hTuple setAltFilename:filename];
  454.     }
  455.     return self;
  456. }
  457. - closeTupleFile:(const char *)filename
  458. {
  459.     id        windowList;
  460.     id        window, document, view;
  461.     id        hTuple;
  462.     int        count;
  463.     
  464.     windowList = [NXApp windowList];
  465.     count = [windowList count];
  466.     while ( count-- ) {
  467.         window = [windowList objectAt:count];
  468.     document = [window delegate];
  469.     if ( [document isKindOf:[DrawDocument class]] ) {
  470.         view = [document view];
  471.         [view closeTupleFile:filename];
  472.     }
  473.     }
  474.     tmpTupleList = [self tupleListForFile:filename];
  475.     count = [tmpTupleList count];
  476.     while ( count-- ) {
  477.         hTuple = [tmpTupleList objectAt:count];
  478.     [tupleList removeObject:hTuple];
  479.     }
  480.     [tupleBrowser reloadColumn:0];
  481.     [self browserSelect:self];
  482.     [tmpTupleList freeObjects];
  483.     return self;
  484. }
  485. - tupleListForFile:(const char *) filename
  486. {
  487.     id        hTuple;
  488.     int        i, count;
  489.     
  490.     if ( tmpTupleList ) {
  491.         [tmpTupleList empty];
  492.     } else {
  493.         tmpTupleList = [[List allocFromZone:[self zone]] initCount: 0];
  494.     }
  495.     count = [tupleList count];
  496.     for ( i = 0; i < count; i++ ) {
  497.         hTuple = [tupleList objectAt:i];
  498.     if ( strcmp( [hTuple filename], filename ) == 0 ) {
  499.             [tmpTupleList addObject:hTuple];
  500.     }
  501.     }
  502.     return tmpTupleList;
  503. }
  504. - showPanel
  505. {
  506.     theInspector = [hDraw newInspector];
  507.     [theInspector show:"Tuple List"];
  508.     [theInspector orderFrontPanel:self];
  509.     return self;
  510. }
  511. - select:sender
  512. {
  513.     selectedTuple = [self currentTuple];
  514.     return self;
  515. }
  516.  
  517. - replace:sender
  518. {
  519.     id             browserMatrix;
  520.     id             doc;
  521.     id            hTuple;
  522.     int            index;
  523.     
  524.     doc = [hDraw currentDocument];
  525.     if ( !doc ) return self;
  526.     graphicView = [doc view];
  527.     browserMatrix = [tupleBrowser matrixInColumn:0];
  528.     index = [browserMatrix selectedRow];
  529.     if ( index < 0 ) return self;
  530.     hTuple = [tupleList objectAt:index];
  531.     selectedTuple = [hTuple ntuple];
  532.     [graphicView graphicsPerform:@selector(replaceTupleWith:)
  533.         with: hTuple andDraw:YES ];
  534.     [[graphicView window] flushWindow];
  535.     return self;
  536. }
  537.  
  538. - close:sender
  539. {
  540.     id        windowList;
  541.     id        window, document, view;
  542.     id        usedTupleList;
  543.     id        hTuple;
  544.     id         browserMatrix;
  545.     int        wcount;
  546.     int        i, irc, index;
  547.     
  548.     browserMatrix = [tupleBrowser matrixInColumn:0];
  549.     index = [browserMatrix selectedRow];
  550.     if ( index < 0 ) return self;
  551.     hTuple = [tupleList objectAt:index];
  552.     windowList = [NXApp windowList];
  553.     wcount = [windowList count];
  554.     while ( wcount-- ) {
  555.         window = [windowList objectAt:wcount];
  556.     document = [window delegate];
  557.     if ( [document isKindOf:[DrawDocument class]] ) {
  558.         view = [document view];
  559.         usedTupleList = [view tupleList];
  560.         i = [usedTupleList indexOf:hTuple];
  561.         if ( i != NX_NOT_IN_LIST ) {
  562.             irc = NXRunAlertPanel( "Close", "Tuple in use",
  563.                                    "OK", NULL, NULL);
  564.         return self;
  565.         }
  566.     }
  567.     }        
  568.     [self closeTupleFile:[hTuple filename]];
  569.     return self;
  570. }
  571. - browserSelect:sender
  572. {
  573.     id            browserMatrix;
  574.     id            hTuple;
  575.     ntuple        nt;
  576.     char        filename[FILENAME_MAX];
  577.     float        mb;
  578.     int            i, index, rows, cols;
  579.  
  580.     browserMatrix = [tupleBrowser matrixInColumn:0];
  581.     index = [browserMatrix selectedRow];
  582.     if ( index < 0 ) {
  583.         for ( i = 0; i < 4; i ++ ) {
  584.         [fileForm setStringValue:"" at:i];
  585.     }
  586.     return self;
  587.     }
  588.     hTuple = [tupleList objectAt:index];
  589.     nt = [hTuple ntuple];
  590.     rows = h_getNtNdata(nt);
  591.     cols = h_getNtDim(nt);
  592.     mb = (4*rows*cols)/1000000.;
  593.     
  594.     strcpy( filename, NXHomeDirectory() );
  595.     index = strspn( [hTuple filename], filename );
  596.     if ( index != (strlen(filename) + 1) ) {
  597.         strcpy( filename, [hTuple filename]); /* not in home directory */
  598.     } else {
  599.         strcpy( filename, "~");        /* file in home directory */
  600.     strcat( filename, [hTuple filename]+(index-1) );
  601.     }
  602.     
  603.     [ fileForm setStringValue:filename at:0];
  604.     [ fileForm setIntValue:cols at:1];
  605.     [ fileForm setIntValue:rows at:2];
  606.     [ fileForm setFloatValue:mb at:3];
  607.     return self;
  608. }    
  609. - updateView
  610. {
  611.     id                  browserMatrix;
  612.  
  613.     browserMatrix = [tupleBrowser matrixInColumn:0];
  614.     if ( !selectedPlot ) {
  615.         [browserMatrix selectCellAt:-1 :-1];
  616.     return self;
  617.     }
  618.     [self setTuple:[selectedPlot ntuple]];
  619.     if (selectedTuple == NULL) {
  620.         [browserMatrix selectCellAt:-1 :-1];
  621.     return self;
  622.     }
  623.     return self;
  624. }
  625. - setTuple:(ntuple) atuple
  626. {
  627.     id                  browserMatrix;
  628.     id            hTuple;
  629.     unsigned int    i, count;
  630.     
  631.     if (selectedTuple == atuple)
  632.     return self;
  633.     selectedTuple = atuple;
  634.     if (selectedTuple == NULL)
  635.     return self;
  636.     browserMatrix = [tupleBrowser matrixInColumn:0];
  637.     count = [tupleList count];
  638.     for ( i = 0; i < count; i++ ) {
  639.         hTuple = [tupleList objectAt:i];
  640.         if ( selectedTuple == [hTuple ntuple] ) {
  641.         [ browserMatrix selectCellAt:i :0];
  642.         [ self browserSelect:self];
  643.         break;
  644.     }
  645.     }
  646.     return self;
  647. }
  648. /* Delegate Methods for NXBrowsers */
  649. - (int) browser: sender fillMatrix: matrix inColumn: (int) column
  650. {
  651.     id                  aCell;
  652.     id            hTuple;
  653.     const char        *title;
  654.     int                 i, count;
  655.  
  656.     count = [tupleList count];
  657.     for (i = 0; i < count; i++) {
  658.     [matrix insertRowAt:i];
  659.     aCell = [matrix cellAt:i :0];
  660.     hTuple = [tupleList objectAt:i];
  661.     title = [hTuple title];
  662.     if ( title && strcmp(title, "") ) {
  663.         [aCell setStringValue:title];
  664.     } else {
  665.         [aCell setStringValue:"<none>"];
  666.     }
  667.     [aCell setLeaf:YES];
  668.     [aCell setLoaded:YES];
  669.     }
  670.     [matrix allowEmptySel:NO];
  671.     return count;
  672. }
  673. - setMsgMatrix:anObject
  674. {
  675.     float    gray;
  676.     int        i, rows, cols;
  677.     
  678.     msgMatrix = anObject;
  679.     gray = [msgMatrix backgroundGray ];
  680.     [msgMatrix getNumRows:&rows numCols:&cols];
  681.     for ( i = 0; i < rows; i++ ) {
  682.        [[msgMatrix cellAt:i :0] setTextGray:gray];
  683.     }
  684.     return self;
  685. }
  686. /* Obsolete methods, maintained for backward compatibility */
  687. - newTuple:(ntuple) nt 
  688. {
  689.  
  690.    [self addTuple:nt];
  691.    return self;
  692. }
  693. @end
  694.